﻿namespace Dhgms.Whipstaff.Universal
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;

    using ReactiveUI;
    using Windows.UI.Xaml.Controls;

    /// <summary>
    /// The base view.
    /// </summary>
    /// <typeparam name="TViewModel">
    /// Type for the view model.
    /// </typeparam>
    public abstract class BaseView<TViewModel> : Page, IViewFor<TViewModel>
        where TViewModel : class
    {
        public BaseView(TViewModel viewModel)
        {
            if (viewModel == null)
            {
                throw new ArgumentNullException("viewModel");
            }

            this.ViewModel = viewModel;

            this.WhenActivated(this.OnDoBindings);
        }

        /// <summary>
        /// The ViewModel corresponding to this specific View. This should be
        ///             a DependencyProperty if you're using XAML.
        /// </summary>
        public TViewModel ViewModel
        {
            get;
            set;
        }

        object IViewFor.ViewModel
        {
            get
            {
                return ViewModel;
            }
            set
            {
                ViewModel = (TViewModel)value;
            }
        }

        /// <summary>
        /// Gets the bindings for the view
        /// </summary>
        /// <returns>Bindings for the view</returns>
        protected abstract IList<IDisposable> GetBindings();

        /// <summary>
        /// Wires up bindings and registers them to be disposed to prevent leaks.
        /// </summary>
        /// <param name="actionToEnsureDisposal">
        /// Used to ensure disposal takes place at the right time.
        /// </param>
        /// <remarks>
        /// Workaround for https://github.com/reactiveui/ReactiveUI/issues/834
        /// </remarks>
        [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed. Suppression is OK here.")]
        private void OnDoBindings(Action<IDisposable> actionToEnsureDisposal)
        {
            var bindings = this.GetBindings();

            foreach (var disposable in bindings)
            {
                actionToEnsureDisposal(disposable);
            }
        }
    }
}
